Use quit-window to hide buffers temporarily displayed by xref
authorDmitry Gutov <dgutov@yandex.ru>
Mon, 19 Jan 2015 02:19:32 +0000 (04:19 +0200)
committerDmitry Gutov <dgutov@yandex.ru>
Mon, 19 Jan 2015 02:19:32 +0000 (04:19 +0200)
* lisp/progmodes/xref.el (xref--display-history): New variable.
(xref--window-configuration): Remove.
(xref--save-to-history): New function.
(xref--display-position): Use it.  Add new argument.
(xref--restore-window-configuration): Remove.
(xref--show-location, xref-show-location-at-point): Update
accordingly.
(xref--xref-buffer-mode): Don't use `pre-command-hook'.
(xref--quit): New command.
(xref-goto-xref): Use it.
(xref--xref-buffer-mode-map): Bind `q' to it.

lisp/ChangeLog
lisp/progmodes/xref.el

index d84e83158c2002155b48be8d29f2d60b71d5301e..39d9436b3f1e6e243c3414be7c257161231526e1 100644 (file)
@@ -1,3 +1,17 @@
+2015-01-19  Dmitry Gutov  <dgutov@yandex.ru>
+
+       * progmodes/xref.el (xref--display-history): New variable.
+       (xref--window-configuration): Remove.
+       (xref--save-to-history): New function.
+       (xref--display-position): Use it.  Add new argument.
+       (xref--restore-window-configuration): Remove.
+       (xref--show-location, xref-show-location-at-point): Update
+       accordingly.
+       (xref--xref-buffer-mode): Don't use `pre-command-hook'.
+       (xref--quit): New command.
+       (xref-goto-xref): Use it.
+       (xref--xref-buffer-mode-map): Bind `q' to it.
+
 2015-01-18  Dmitry Gutov  <dgutov@yandex.ru>
 
        * progmodes/xref.el (xref-goto-xref): Perform the jump even inside
index 59da57932956117634ad627acae513c512e5c0a0..4431cb5d3b3a0ed8653a8d9104816c47438a9688 100644 (file)
@@ -51,6 +51,7 @@
 (require 'cl-lib)
 (require 'eieio)
 (require 'ring)
+(require 'pcase)
 
 (defgroup xref nil "Cross-referencing commands"
   :group 'tools)
@@ -333,19 +334,31 @@ WINDOW controls how the buffer is displayed:
 
 ;; The xref buffer is used to display a set of xrefs.
 
-(defvar-local xref--window-configuration nil)
+(defvar-local xref--display-history nil
+  "List of pairs (BUFFER . WINDOW), for temporarily displayed buffers.")
 
-(defun xref--display-position (pos other-window recenter-arg)
-  ;; show the location, but don't hijack focus.
+(defun xref--save-to-history (buf win)
+  (let ((restore (window-parameter win 'quit-restore)))
+    ;; Save the new entry if the window displayed another buffer
+    ;; previously.
+    (when (and restore (not (eq (car restore) 'same)))
+      (push (cons buf win) xref--display-history))))
+
+(defun xref--display-position (pos other-window recenter-arg xref-buf)
+  ;; Show the location, but don't hijack focus.
   (with-selected-window (display-buffer (current-buffer) other-window)
     (goto-char pos)
-    (recenter recenter-arg)))
+    (recenter recenter-arg)
+    (let ((buf (current-buffer))
+          (win (selected-window)))
+      (with-current-buffer xref-buf
+        (xref--save-to-history buf win)))))
 
 (defun xref--show-location (location)
   (condition-case err
-      (progn
+      (let ((xref-buf (current-buffer)))
         (xref--goto-location location)
-        (xref--display-position (point) t 1))
+        (xref--display-position (point) t 1 xref-buf))
     (user-error (message (error-message-string err)))))
 
 (defun xref-show-location-at-point ()
@@ -353,14 +366,8 @@ WINDOW controls how the buffer is displayed:
   (interactive)
   (let ((loc (xref--location-at-point)))
     (when loc
-      (setq xref--window-configuration (current-window-configuration))
       (xref--show-location loc))))
 
-(defun xref--restore-window-configuration ()
-  (when xref--window-configuration
-    (set-window-configuration xref--window-configuration)
-    (setq xref--window-configuration nil)))
-
 (defun xref-next-line ()
   "Move to the next xref and display its source in the other window."
   (interactive)
@@ -385,16 +392,15 @@ WINDOW controls how the buffer is displayed:
   (let ((loc (or (xref--location-at-point)
                  (error "No reference at point")))
         (window xref--window))
-    (quit-window)
+    (xref--quit)
     (xref--pop-to-location loc window)))
 
 (define-derived-mode xref--xref-buffer-mode fundamental-mode "XREF"
   "Mode for displaying cross-references."
-  (setq buffer-read-only t)
-  (add-hook 'pre-command-hook #'xref--restore-window-configuration nil t))
+  (setq buffer-read-only t))
 
 (let ((map xref--xref-buffer-mode-map))
-  (define-key map (kbd "q") #'quit-window)
+  (define-key map (kbd "q") #'xref--quit)
   (define-key map (kbd "n") #'xref-next-line)
   (define-key map (kbd "p") #'xref-prev-line)
   (define-key map (kbd "RET") #'xref-goto-xref)
@@ -404,6 +410,18 @@ WINDOW controls how the buffer is displayed:
   (define-key map (kbd ".") #'xref-next-line)
   (define-key map (kbd ",") #'xref-prev-line))
 
+(defun xref--quit ()
+  "Quit all windows in `xref--display-history', then quit current window."
+  (interactive)
+  (let ((window (selected-window))
+        (history xref--display-history))
+    (setq xref--display-history nil)
+    (pcase-dolist (`(,buf . ,win) history)
+      (when (and (window-live-p win)
+                 (eq buf (window-buffer win)))
+        (quit-window nil win)))
+    (quit-window nil window)))
+
 (defconst xref-buffer-name "*xref*"
   "The name of the buffer to show xrefs.")